<?php
/**
 * +-------------------------------------------------------------
 * |Caption:
 * +-------------------------------------------------------------
 * |Author: Lenny
 * +-------------------------------------------------------------
 * |Email:  1685964109@qq.com
 * +-------------------------------------------------------------
 * |Date:   2024/6/18 上午9:21
 * +-------------------------------------------------------------
 */

namespace app\common\traits;

use app\common\enum\Status;
use app\common\exception\BaseException;
use app\common\model\SalesmanDealer;
use app\Request;
use Exception;
use jianyan\excel\Excel;
use think\facade\Db;
use think\response\Json;
use app\common\service\annotation\NodeAnnotation;

trait CurdTrait
{
    /**
     * @NodeAnnotation (title="查找单条记录")
     */
    public function find($data, array $with = []): Json
    {
        $query = $this->model->with($with);
        $res   = is_array($data) ? $query->where($data)->find() : $query->find((int)$data);
        return $this->success($res);
    }

    /**
     * @NodeAnnotation (title="列表")
     */
    public function list(): Json
    {
        // 解析搜索参数，构建基础查询条件
        list($limit, $mainWhere, $joinWhere) = $this->buildSearchParams();
        // 解析关联表配置
        $joinTables = [];
        if ($this->joinTable) $joinTables = array_filter(explode(',', $this->joinTable));
        // 主表模型名
        $mainTable = $this->model->getName();
        // 构建基础查询，应用默认条件和排除字段
        $query = $this->model->alias($mainTable);
        // 处理自定义条件
        $query = $this->buildCustomCondition($query, $mainWhere);
        // 处理关联表查询
        $list = $this->buildRelationCondition($query, $joinTables, $joinWhere, $limit);
        // 处理关联表查询条件
        if ($this->each) $list = $this->each($list);
        return $this->success($list);
    }

    /**
     * 列表数据处理
     * @param $list
     * @return mixed
     */
    public function each($list)
    {
        return $list->each(function ($vo)
        {
            return $vo;
        });
    }

    /**
     * @NodeAnnotation (title="新增")
     * @throws BaseException
     */
    public function add(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $this->sceneValidate($post, 'add');
        if (!empty($this->groupId)) $post['group_id'] = $this->groupId;
        if (!empty($this->companyId)) $post['company_id'] = $this->companyId;
        try {
            $this->model->transaction(function () use ($post)
            {
                $this->model->save($post);
                // 如果有需要添加的关联表数据
                if ($this->joinAddTable) $this->joinAddTable($post);
            });
        } catch (\Exception $e) {
            return $this->error('新增失败:' . $e->getMessage());
        }
        return $this->success('新增成功');
    }

    /**
     * @NodeAnnotation (title="编辑")
     * @throws BaseException
     */
    public function edit(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $this->sceneValidate($post, 'edit');
        $row = $this->model->find($post['id']);
        if (!$row) return $this->error('数据不存在！');
        try {
            $this->model->transaction(function () use ($post, $row)
            {
                $row->save($post);
                // 如果有需要更新的关联表数据
                if ($this->joinUpdateTable) $this->joinUpdateTable($post, $row);
            });
        } catch (\Exception $e) {
            return $this->error('保存失败:' . $e->getMessage());
        }
        return $this->success('保存成功');
    }

    /**
     * @NodeAnnotation (title="字段修改")
     * @throws BaseException
     */
    public function modify(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $this->sceneValidate($post, 'modify');
        $row = $this->model->find($post['id']);
        if (!$row) return $this->error('数据不存在');
        try {
            $this->model->transaction(function () use ($post, $row)
            {
                $row->save([
                                   $post['field'] => $post['value'],
                           ]);
            });
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
        return $this->success('操作成功');
    }

    /**
     * @NodeAnnotation(title="详情")
     */
    public function detail($id): Json
    {
        $with = array_filter(explode(',', $this->joinTable));
        $row  = $this->model->with($with);
        $row  = $row->find($id);
        if (!$row) return $this->error('数据不存在！');
        return $this->success($row);
    }

    /**
     * @NodeAnnotation (title="删除")
     * @throws BaseException
     */
    public function del(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $rule = [
                'id' => 'require'
        ];
        $this->validate($post, $rule);
        $ids = explode(',', $post['id']);
        try {
            foreach ($ids as $v) {
                $sql = $this->model;
                if ($this->joinDelTable) {
                    // 关联删除
                    $row = $sql->with(explode(',', $this->joinDelTable))->find($v);
                    if ($row) $row->together(explode(',', $this->joinDelTable))->delete();
                } else {
                    $row = $sql->find($v);
                    if($row) $row->delete();
                }
            }
        } catch (\Exception $e) {
            return $this->error('删除失败:' . $e->getMessage());
        }
        return $this->success('删除成功');
    }

    /**
     * 目前不完善，不灵活
     * @NodeAnnotation(title="模版下载")
     */
    public function template(): Json|bool
    {
        $importHeader = $this->importHeader;
        $header       = array_map(function ($vo, $hed) use ($importHeader)
        {
            return [
                    $hed, $vo
            ];
        }, $this->defaultTemplate, $importHeader);
        if (!$this->importHeader) return $this->error('未设置下载表头,请联系管理员');
        if (!$this->fileName) return $this->error('未设置下载文件名,请联系管理员');
        $fileName = $this->fileName;
        return Excel::exportData([], $header, $fileName, 'xlsx');
    }


    /**
     * 目前不完善，不灵活
     * @NodeAnnotation(title="导出")
     */
    public function export(): bool
    {
        // 构建查询
        list($limit, $where) = $this->buildSearchParams();
        // 获取表名
        $tableName = $this->model->getName();
        $tableName = humpToLine(lcfirst($tableName));
        // 获取表前缀
        $prefix = config('database.connections.mysql.prefix');
        // 获取表字段
        $dbList = Db::query("show full columns from {$prefix}{$tableName}");
        // 设置表头
        $header = [];
        // 循环表字段
        foreach ($dbList as $vo) {
            $comment = !empty($vo['Comment']) ? $vo['Comment'] : $vo['Field'];
            if (!in_array($vo['Field'], $this->noExportFields)) {
                $header[] = [$comment, $vo['Field']];
            }
        }
        $list     = $this->model
                ->where($where)
                ->where($this->defaultWhere)
                ->where('status', Status::NORMAL)
                ->limit($limit ?? 100000)
                ->order('id', 'desc')
                ->select()
                ->toArray();
        $fileName = time();
        return Excel::exportData($list, $header, $fileName, 'xlsx');
    }

    /**
     * 目前不完善，不灵活
     * @NodeAnnotation(title="导入")
     * @throws BaseException
     */
    public function import(Request $request): Json
    {
        $this->checkPost();
        $file = $request->file('file');
        if (!$file) return $this->error('请上传文件！');
        // 保存文件到临时目录
        $savePath = $file->move('storage' . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR);
        // 获取文件的完整路径
        $savePath = $savePath->getPathname();
        try {
            $data = Excel::import($savePath, 1, false, 'Xlsx', './storage/temp/excelImg/');
            if (!$data) throw new BaseException(['message' => '文件内容为空！']);
            if (!$this->importHeader) throw new BaseException(['message' => '请联系管理设置文件模版！']);
            if (array_filter($data[0]) != $this->importHeader) throw new BaseException(['message' => '文件格式不正确！']);
            // 格式化数据
            $infoArray = array_map(function ($row)
            {
                if ($this->appName == 'admin') {
                    $newRow['group_id'] = $this->groupId;
                } else {
                    $newRow['company_id'] = $this->companyId;
                }
                return $newRow;
            }, $data);

            // 去掉表头
            unset($infoArray[0]);
            // 去除空数组
            $infoArray = array_filter($infoArray);
            $this->model->transaction(function () use ($infoArray, &$save)
            {
                $save = $this->model->insertAll($infoArray);
            });
        } catch (Exception $e) {
            @unlink($savePath);
            return $this->error('导入失败' . $e->getMessage());
        }
        @unlink($savePath);
        return $this->success('导入成功！');
    }

    protected function actionImports(mixed $data)
    {
    }

}